﻿Option Strict On

Imports System.ComponentModel

Public Class frmBatchProcess

    Private WithEvents bw As New BackgroundWorker

    Private Sub frmBatchProcess_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Icon = My.Resources.Main

        With bw
            .WorkerReportsProgress = True
            .WorkerSupportsCancellation = True
        End With

        txtFolder.Text = My.Settings.LastBatchFolder
        chkCreateWaveformImage.Checked = My.Settings.LastBatchGenerateImage
        chkProcessSubfolders.Checked = My.Settings.LastBatchSubfolders
        chkSkipPrevious.Checked = My.Settings.LastBatchSkipprevious
    End Sub

    Private Sub frmBatchProcess_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
        If bw.IsBusy Then
            MsgBox("Folders are currently being processed. Stop processing before closing this form.", vbOKOnly Or MsgBoxStyle.Exclamation, "Processing Busy")
            e.Cancel = True
            Exit Sub
        End If

        bw.Dispose()

        With My.Settings
            .LastBatchFolder = txtFolder.Text
            .LastBatchGenerateImage = chkCreateWaveformImage.Checked
            .LastBatchSubfolders = chkProcessSubfolders.Checked
            .LastBatchSkipprevious = chkSkipPrevious.Checked
            .Save()
        End With

    End Sub

    Private Sub txtFolder_Click(sender As Object, e As EventArgs) Handles txtFolder.Click
        cmdBrowseFolder.PerformClick()
    End Sub

    Private Sub cmdBrowseFolder_Click(sender As Object, e As EventArgs) Handles cmdBrowseFolder.Click
        If dlgFolder.ShowDialog = DialogResult.OK Then
            txtFolder.Text = dlgFolder.SelectedPath
        End If

    End Sub

    Private Sub cmdProcess_Click(sender As Object, e As EventArgs) Handles cmdProcess.Click
        If cmdProcess.Text.StartsWith("Stop") Then
            bw.CancelAsync()
            cmdProcess.Text = "Stopping..."

        Else
            If Not String.IsNullOrEmpty(txtFolder.Text) Then
                cmdProcess.Text = "Stop"
                txtProcessingLog.AppendText("Processing started." & vbCrLf)
                bw.RunWorkerAsync(New WorkerArgs With {.RootFolder = txtFolder.Text, .Recursive = chkProcessSubfolders.Checked, .SkipPreviouslyProcessed = chkSkipPrevious.Checked, .CreateImage = chkCreateWaveformImage.Checked})

            End If

        End If

    End Sub

    Private Sub cmdClose_Click(sender As Object, e As EventArgs) Handles cmdClose.Click
        Me.Close()

    End Sub

    Private Sub bw_DoWork(sender As Object, e As DoWorkEventArgs) Handles bw.DoWork
        Dim args As WorkerArgs
        Dim root As IO.DirectoryInfo

        Try
            args = DirectCast(e.Argument, WorkerArgs)
            root = New IO.DirectoryInfo(args.RootFolder)

            ProcessFolder(args.RootFolder, args.CreateImage, args.Recursive, args.SkipPreviouslyProcessed)

        Finally
            If bw.CancellationPending Then bw.ReportProgress(100, "Cancelled" & vbCrLf)

        End Try

    End Sub

    Private Sub bw_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles bw.ProgressChanged
        txtProcessingLog.AppendText(e.UserState.ToString)
    End Sub

    Private Sub bw_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bw.RunWorkerCompleted
        cmdProcess.Text = "Process"
        If e.Error IsNot Nothing Then
            txtProcessingLog.AppendText($"An error occurred during processing: {e.Error.Message}" & vbCrLf)
        End If

        txtProcessingLog.AppendText("Processing complete." & vbCrLf)

    End Sub

    Private Sub ProcessFolder(foldername As String, createImage As Boolean, recursive As Boolean, skipPrevious As Boolean)
        Dim data As BassFunctions
        Dim fl As IO.DirectoryInfo
        Dim fileName As String

        fl = New IO.DirectoryInfo(foldername)
        fileName = IO.Path.Combine(fl.FullName, $"{If(fl.Parent Is Nothing, "", fl.Parent.Name & " - ")}{fl.Name}.wf")

        If fl.GetFiles.Count > 0 Then
            If IO.File.Exists(fileName) AndAlso skipPrevious Then
                bw.ReportProgress(1, $"Skipping {New String(" "c, fl.FullName.ToCharArray.Where(Function(x) x = "\").Count * 2)} {fl.Name} (previously processed)" & vbCrLf)

            Else
                bw.ReportProgress(1, $"Processing {New String(" "c, fl.FullName.ToCharArray.Where(Function(x) x = "\").Count * 2)} {fl.Name}" & vbCrLf)

                Try
                    data = New BassFunctions
                    With data
                        .Filename = fileName
                        .ReadTracksFromFolder(foldername)
                        .WaveformData = New Misc.WaveForm(data.Filename & ".wav")
                        .WaveformData.RenderStart(False, BASSFlag.BASS_SAMPLE_FLOAT Or BASSFlag.BASS_STREAM_PRESCAN)
                        .Save(data.Filename)
                    End With

                    If Not My.Settings.DoNotDeleteWave Then
                        IO.File.Delete(data.Filename & ".wav")
                    End If

                    If createImage AndAlso IO.File.Exists(data.Filename) Then
                        BassFunctions.CreateWaveformImage(New String() {data.Filename}, data.Filename.TrimEnd(".wf".ToCharArray) & ".jpg")
                    End If

                Catch ex As Exception
                    bw.ReportProgress(1, $"Error processing {fl.Name}: {ex.Message}" & vbCrLf)
                End Try
            End If

        Else
            bw.ReportProgress(1, $"Skipping {New String(" "c, fl.FullName.ToCharArray.Where(Function(x) x = "\").Count * 2)} {fl.Name} (empty folder)" & vbCrLf)

        End If

        If Not bw.CancellationPending AndAlso recursive Then
            For Each subfl As IO.DirectoryInfo In fl.GetDirectories.Where(Function(x) Not CBool(x.Attributes And IO.FileAttributes.System))
                ProcessFolder(subfl.FullName, createImage, recursive, skipPrevious)

                If bw.CancellationPending Then Exit Sub

            Next

        End If

    End Sub

    Private Class WorkerArgs
        Public Property RootFolder As String
        Public Property Recursive As Boolean
        Public Property SkipPreviouslyProcessed As Boolean
        Public Property CreateImage As Boolean
    End Class

End Class